package com.dimples.dd.auth.core.oauth2.handler;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.dimples.dd.auth.core.util.LoginLogUtil;
import com.dimples.dd.common.enums.UserTypeEnum;
import com.dimples.dd.common.result.CommonResult;
import com.dimples.dd.common.result.ResultCode;
import com.dimples.dd.system.enums.logger.LoginLogTypeEnum;
import com.dimples.dd.system.enums.logger.LoginResultEnum;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import java.io.IOException;

/**
 * 认证失败处理器
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2024/5/28
 */
@Slf4j
public class DDAuthenticationFailureHandler implements AuthenticationFailureHandler {

    /**
     * MappingJackson2HttpMessageConverter 是 Spring 框架提供的一个 HTTP 消息转换器，用于将 HTTP 请求和响应的 JSON 数据与 Java 对象之间进行转换
     */
    private final HttpMessageConverter<Object> accessTokenHttpResponseConverter = new MappingJackson2HttpMessageConverter();


    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
        log.error("认证失败:{} \n {}", exception.getMessage(), ExceptionUtil.stacktraceToString(exception));
        OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
        ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
        CommonResult<?> result;
        String description = error.getDescription();
        String errorCode = error.getErrorCode();
        if (StrUtil.containsIgnoreCase(errorCode, "invalid token")) {
            result = CommonResult.error(ResultCode.TOKEN_INVALID);
        } else if (StrUtil.containsIgnoreCase(errorCode, "OAuth 2.0 Parameter: grant_type")) {
            result = CommonResult.error(ResultCode.TOKEN_REFRESH_ERROR);
        } else if (StrUtil.equals(description, "用户名或密码错误")) {
            result = CommonResult.error(ResultCode.AUTH_LOGIN_BAD_CREDENTIALS);
            LoginLogUtil.createLoginLog(errorCode, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.BAD_CREDENTIALS, UserTypeEnum.ADMIN);
        } else if (StrUtil.equals(description, "该账户已被禁用!")) {
            result = CommonResult.error(ResultCode.AUTH_LOGIN_USER_DISABLED);
            LoginLogUtil.createLoginLog(errorCode, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.USER_DISABLED, UserTypeEnum.ADMIN);
        } else if (StrUtil.equals(description, ResultCode.VALIDATE_CODE_ERROR.getMsg())) {
            result = CommonResult.error(ResultCode.VALIDATE_CODE_ERROR);
            LoginLogUtil.createLoginLog(errorCode, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR, UserTypeEnum.ADMIN);
        } else if (StrUtil.equals(description, ResultCode.VALIDATE_CODE_NOT_NULL.getMsg())) {
            result = CommonResult.error(ResultCode.VALIDATE_CODE_NOT_NULL);
            LoginLogUtil.createLoginLog(errorCode, LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_NOT_FOUND, UserTypeEnum.ADMIN);
        } else {
            result = CommonResult.error(description);
        }
        accessTokenHttpResponseConverter.write(result, null, httpResponse);
    }
}




















